package com.wt.wechatTools.service;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.annotation.SuppressLint;
import android.app.Application;
import android.app.Notification;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.wt.wechatTools.room.WorkRepository;
import com.wt.wechatTools.room.entity.ContactsEntity;
import com.wt.wechatTools.room.entity.UserEntity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//https://www.jianshu.com/p/4cd8c109cdfb
//https://www.jianshu.com/p/7b91e3702328
//https://segmentfault.com/a/1190000015345637

public class WechatToolsService extends AccessibilityService {
    private static final String TAG = "WechatToolsService";
    private WorkRepository workRepository;
    private List<ContactsEntity> contactsEntityList = new ArrayList<>(); //任务目录
    private ContactsEntity contactsEntity;
    private List<ContactsEntity> cnUpdateList = new ArrayList<>(); //在任务结束时需要更新的目录
    private Integer delay;
    private Integer tastBatch;
    private UserEntity userEntity;

    //悬浮框
    public static boolean isStarted = false;
    private WindowManager windowManager;
    private WindowManager.LayoutParams layoutParams;
    private Button btnStart;

    @Override
    public void onCreate() {
        super.onCreate();
        isStarted = true;
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        layoutParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        layoutParams.format = PixelFormat.RGBA_8888;
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        layoutParams.width = 300;
        layoutParams.height = 166;

        //获取屏幕大小
        Point screenSize = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            windowManager.getDefaultDisplay().getRealSize(screenSize);
        }

        //设置在屏幕显示的位置
        layoutParams.x = screenSize.x - 310;
        layoutParams.y = screenSize.y - 1000;
    }

    /**
     * 打开无障碍服务时调用此方法
     * 获取基础数据
     * 系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        //销毁悬浮窗
        if (windowManager != null && btnStart != null) {
            windowManager.removeView(btnStart);
            btnStart = null;
        }
        showFloatingWindow();
    }

    /**
     * 目前仅监听了typeWindowStateChanged事件
     * 当系统检测到与无障碍服务指定的事件过滤参数匹配的 AccessibilityEvent
     * 时，就会回调此方法。例如，当用户点击按钮，或者聚焦于某个应用（无障碍
     * 服务正在为该应用提供反馈）中的界面控件时。出现这种情况时，系统会调用
     * 此方法，并传递关联的 AccessibilityEvent，然后服务会对该类进行解释并
     * 使用它来向用户提供反馈。此方法可能会在您的服务的整个生命周期内被调用多次。
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            //获取事件具体信息
            Parcelable parcelable = event.getParcelableData();
            //如果是下拉通知栏消息
            if (parcelable instanceof Notification) {
            } else {
                //其它通知信息，包括Toast
                String toastMsg = (String) event.getText().get(0);
                if (toastMsg == "微信：操作过于频繁，请稍后再试。") {
                    //关闭服务
                    this.disableSelf();
                }
                Log.d(TAG, "onAccessibilityEvent: " + toastMsg);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void showFloatingWindow() {
        if (Settings.canDrawOverlays(this)) {
            btnStart = new Button(getApplicationContext());
            btnStart.setText("启动服务");
            btnStart.setBackgroundColor(Color.RED);
            windowManager.addView(btnStart, layoutParams);

            /**
             * 启动服务
             */
            btnStart.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.d(TAG, "showFloatingWindow: 任务开始了！");
                    //获取任务数据
                    getData();
                }
            });
        }
    }

    /**
     * 获取任务数据
     */
    private void getData() {
        MyHandler myHandler = new MyHandler(getApplication(), this);
        //获取数据
        new Thread() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            public void run() {
                Message message = new Message();
                //初始化WorkRepository 数据仓库方法
                workRepository = new WorkRepository(getApplicationContext());
                //获取任务参数
                userEntity = workRepository.getUser();

                String endTimeString = userEntity.getEndTime();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                Date nowDate = new Date();
                try {
                    Date endTime = sdf.parse(endTimeString);
                    if (endTime.getTime() > nowDate.getTime()) {
                        //每次任务执行数量
                        Integer count = userEntity.getCount();
                        //任务批次
                        tastBatch = userEntity.getTaskBatch();
                        tastBatch++;
                        userEntity.setTaskBatch(tastBatch);
                        //任务间隔
                        delay = userEntity.getSpeed();

                        //获取任务列表
                        contactsEntityList = workRepository.getTaskList(count);
//                        contactsEntityList.add(new ContactsEntity(null, "", "17628683161", 1, null));
                        if (contactsEntityList.size() == 0) {
                            //向主进程推送消息：未获取到任务清单
                            message.what = 1;
                            message.obj = "未获取到任务清单!";
                            myHandler.sendMessage(message);
                            return;
                        }
                        //开始任务
                        clickFirst();
                    } else {
                        message.what = 1;
                        message.obj = "你的套餐已过期！";
                        myHandler.sendMessage(message);
                        return;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
        btnStart.setText("任务已开始，请勿触碰！");
    }

    //使用服务的过程中如果出现异常，服务会自动停止。
    //异步的方法
    //https://www.runoob.com/w3cnote/android-tutorial-handler-message.html
    //https://blog.csdn.net/qq_41673194/article/details/80022875
    private static class MyHandler extends Handler {
        //初始化这个类
        private Application application;
        private WechatToolsService wechatToolsService;

        public MyHandler(Application application, WechatToolsService wechatToolsService) {
            this.application = application;
            this.wechatToolsService = wechatToolsService;
        }

        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1: //未获取到任务清单、请充值
                    Toast.makeText(application.getBaseContext(), msg.obj.toString(), Toast.LENGTH_LONG).show();
                    //关闭服务
                    wechatToolsService.disableSelf();
                    break;
            }
        }
    }

    /**
     * 当无障碍服务关闭时会调用此方法。
     */
    @Override
    public boolean onUnbind(Intent intent) {
        //销毁悬浮窗
        if (windowManager != null && btnStart != null) {
            windowManager.removeView(btnStart);
            btnStart = null;
        }
        Toast.makeText(this, "任务执行结束！WECHAT_TS已停止！", Toast.LENGTH_SHORT).show();
        if (cnUpdateList.size() > 0) {
            Log.d(TAG, "onUnbind: 开始执行本地数据更新的任务！" + cnUpdateList.size());
            new Thread() {
                @Override
                public void run() {
                    //数据库操作
                    workRepository.updateContactList(cnUpdateList);
                    workRepository.updateUser(userEntity);
                }
            }.start();
        }
        return super.onUnbind(intent);
    }

    /**
     * 当系统想要中断您的服务正在提供的反馈（通常是为了响应将焦点移到其他
     * 控件等用户操作）时，就会调用此方法。此方法可能会在您的服务的整个生命
     * 周期内被调用多次。
     */
    @Override
    public void onInterrupt() {

    }

    /**
     * 获取节点  尝试获取10次节点，如果超过10次没有获取到节点那么就 关闭服务。
     *
     * @param nodeText
     * @return
     */
    private AccessibilityNodeInfo getNodeBaseByText(String nodeText) {
        AccessibilityNodeInfo nodeEnd = null;
        List<AccessibilityNodeInfo> listByText = new ArrayList<>();
        try {
            Integer count = 0;
            while (count < 10) {
                AccessibilityNodeInfo nodeBase = getRootInActiveWindow();
                if (nodeBase == null) {
                    Log.d(TAG, "getNodeBaseByText: 未获取到根节点");
                    continue;
                } else {
                    listByText = nodeBase.findAccessibilityNodeInfosByText(nodeText);
                    if (listByText.size() == 1) {
                        Log.d(TAG, "getNodeBaseByText: 找到节点");
                        nodeEnd = listByText.get(0);
                        break;
                    }
                }
                Thread.sleep(delay);
                count++;
            }
            //如果到第10次都没有获取到节点，那么结束服务
            if (listByText.size() == 0) {
                //结束任务
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    this.disableSelf();
                }
            }
        } catch (Exception e) {
            Log.d(TAG, "getNodeBaseByText: " + e);
        }
        return nodeEnd;
    }

    /**
     * 获取节点  尝试获取10次节点  如果未找到 返回空
     *
     * @param nodeText
     * @return
     */
    private AccessibilityNodeInfo getNodeBaseByTextNew(String nodeText) {
        AccessibilityNodeInfo nodeEnd = null;
        List<AccessibilityNodeInfo> listByText = new ArrayList<>();
        try {
            Integer count = 0;
            while (count < 10) {
                AccessibilityNodeInfo nodeBase = getRootInActiveWindow();
                if (nodeBase == null) {
                    Log.d(TAG, "getNodeBaseByText: 未获取到根节点");
                    continue;
                } else {
                    listByText = nodeBase.findAccessibilityNodeInfosByText(nodeText);
                    if (listByText.size() == 1) {
                        Log.d(TAG, "getNodeBaseByText: 找到节点");
                        nodeEnd = listByText.get(0);
                        break;
                    }
                }
                Thread.sleep(delay);
                count++;
            }
        } catch (Exception e) {
            Log.d(TAG, "getNodeBaseByText: " + e);
        }
        return nodeEnd;
    }

    /**
     * 获取节点  尝试获取10次节点，如果超过10次没有获取到节点那么就 关闭服务。
     * @param viewId
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private AccessibilityNodeInfo getNodeBaseByViewId(String viewId) {
        AccessibilityNodeInfo nodeEnd = null;
        List<AccessibilityNodeInfo> list = new ArrayList<>();
        try {
            Integer count = 0;
            while (count < 10) {
                AccessibilityNodeInfo nodeBase = getRootInActiveWindow();
                if (nodeBase == null) {
                    Log.d(TAG, "getNodeBaseByViewId: 未获取到根节点");
                } else {
                    list = nodeBase.findAccessibilityNodeInfosByViewId(viewId);
                    if (list.size() > 0) {
                        nodeEnd = list.get(0);
                        break;
                    }
                }
                Thread.sleep(delay);
                count++;
            }
            //如果到第10次都没有获取到节点，那么结束服务
            if (list.size() == 0) {
                //结束任务
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    this.disableSelf();
                }
            }
        } catch (Exception e) {
            Log.d(TAG, "getNodeBaseByViewId: " + e);
        }
        return nodeEnd;
    }

    /**
     * 第一步 ：点击  com.tencent.mm:id/he6
     * @return 是否操作成
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void clickFirst() {
        try {
            Thread.sleep(500);
            Log.d(TAG, "clickFirst: bengin");
            AccessibilityNodeInfo nodeEnd = getNodeBaseByViewId("com.tencent.mm:id/fdi");
            // 点击
            boolean isClick = nodeEnd.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            if (isClick) {
                Log.d(TAG, "clickFirst: 点击 成功！");
                //第二步
                clickSecond();
                return;
            } else {
                Log.d(TAG, "clickFirst: 点击 失败！");
                //结束任务
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    this.disableSelf();
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "clickFirst: 错误", e);
            //结束任务
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                this.disableSelf();
            }
        }
    }

    /**
     * 第二步 ：   com.tencent.mm:id/bxz
     * 输入要搜索的账号
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void clickSecond() {
        try {
            Log.d(TAG, "clickSecond: bengin");
            Thread.sleep(delay);
//           参考 https://developer.android.google.cn/reference/android/accessibilityservice/AccessibilityService?hl=en#findFocus(int)
            //查找当前具有焦点的输入框
            AccessibilityNodeInfo nodeEditText = null;
            Integer cc = 0;
            while (cc < 10) {
                nodeEditText = findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
                if (nodeEditText != null) {
                    break;
                }
                cc++;
                Thread.sleep(800);
            }
            if (nodeEditText == null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    this.disableSelf();
                }
            }

            //获取这次任务需要的电话
            if (contactsEntityList.size() == 0) {
                //关闭服务
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    //结束任务
                    this.disableSelf();
                    return;
                }
            }

            contactsEntity = contactsEntityList.get(0);
            //准备数据
            ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 2, tastBatch);
            //加入集合用于在任务结束时，更新数据。
            cnUpdateList.add(cn);
            //删除元素
            contactsEntityList.remove(0);

            //andorid 10以后的版本在后台执行的程序，无法读取剪切板。同时目前遇到一个无法设置剪切板的bug，只有第一次能设置成功。
            boolean isOK = false;
            Log.d(TAG, "clickSecond: " + contactsEntity.getCellPhone());
            //输入内容
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Bundle arguments = new Bundle();
                arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, contactsEntity.getCellPhone());
                nodeEditText.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
                isOK = nodeEditText.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
            } else {
                //https://blog.csdn.net/qq_19694479/article/details/100134460
                Log.d(TAG, "clickSecond: 您的系统版本不支持输入。需要android 5.0以上的系统");
            }
            if (isOK) {
                Log.d(TAG, "clickSecond: 输入成功！" + contactsEntity.getCellPhone());
                clickThree();
            } else {
                Log.d(TAG, "clickSecond: 输入失败！" + contactsEntity.getCellPhone());
            }
        } catch (Exception e) {
            Log.e(TAG, "clickSecond: 错误", e);
        }
    }

    /**
     * 第三步  点击搜索
     */
    private void clickThree() {
        try {
            Thread.sleep(delay);
            Log.d(TAG, "clickThree: ");
            //获取当前页面的根节点
            //https://developer.android.google.cn/reference/kotlin/android/accessibilityservice/AccessibilityService?hl=en#getrootinactivewindow
            AccessibilityNodeInfo nodeInfo = getNodeBaseByTextNew("查找手机/QQ号:" + contactsEntity.getCellPhone());
            if (nodeInfo == null) {
                //那么,就将这一列，先放到临时的集合里。在任务结束时，更新数据。就更新此好友的状态为3(无法查找)
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 3, tastBatch);
                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                backInsert2();
                return;
            }
            AccessibilityNodeInfo nodeEnd = nodeInfo.getParent();
            boolean isClick = nodeEnd.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            if (isClick) {
                Log.d(TAG, "clickThree: 点击 搜索:" + contactsEntity.getCellPhone() + "成功！");
                //添加到通讯录
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    addContacts();
                }
            } else {
                Log.d(TAG, "clickThree: 点击 搜索:" + contactsEntity.getCellPhone() + "失败！");
            }
        } catch (Exception e) {
            Log.e(TAG, "clickThree: 错误", e);
        }
    }

    /**
     * 添加到通讯录
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    private void addContacts() {
        try {
            Log.d(TAG, "search2: ");
            Thread.sleep(delay);

            //获取根节点
            AccessibilityNodeInfo nodeBase = null;
            Integer addCount = 0;
            while (addCount < 10) {
                nodeBase = getRootInActiveWindow();
                if (nodeBase != null) {
                    break;
                }
                addCount++;
                if (addCount == 10) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        this.disableSelf();
                    }
                }
                Thread.sleep(800);
            }

            //关闭服务
            if (nodeBase == null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    this.disableSelf();
                }
                return;
            }

            //判断是否能够搜索到此用户
            List<AccessibilityNodeInfo> isSS = nodeBase.findAccessibilityNodeInfosByText("用户不存在");
            if (isSS.size() == 1) {
                Log.d(TAG, "search2: 用户不存在");
                // 已经是好友了，该用户不存在，也会导致无法找到关键字  添加到通讯录。
                //那么,就将这一列，先放到临时的集合里。在任务结束时，更新数据。就更新此好友的状态为3(无法查找)
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 3, tastBatch);
                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                //进入输入流程
                backInsert3();
                return;
            }

            //判断是否能够搜索到此用户
            List<AccessibilityNodeInfo> isCheck = nodeBase.findAccessibilityNodeInfosByText("该用户不存在");
            if (isCheck.size() == 1) {
                Log.d(TAG, "search2: 该用户不存在");
                // 已经是好友了，该用户不存在，也会导致无法找到关键字  添加到通讯录。
                //那么,就将这一列，先放到临时的集合里。在任务结束时，更新数据。就更新此好友的状态为3(无法查找)
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 3, tastBatch);
                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                //进入输入流程
                backInsert1();
                return;
            }

            //判断此用户是否已添加
            List<AccessibilityNodeInfo> isAdd = nodeBase.findAccessibilityNodeInfosByText("发消息");
            if (isAdd.size() == 1) {
                Log.d(TAG, "search2: 该用户已添加");
                // 已经是好友了，该用户不存在，也会导致无法找到关键字  添加到通讯录。
                //那么,就将这一列，先放到临时的集合里。在任务结束时，更新数据。就更新此好友的状态为3(无法查找)
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 4, tastBatch);
                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                backInsert2();
                return;
            }

            //判断被搜帐号状态异常，无法显示
            List<AccessibilityNodeInfo> isError = nodeBase.findAccessibilityNodeInfosByText("被搜帐号状态异常，无法显示");
            if (isError.size() == 1) {
                Log.d(TAG, "search2: 被搜帐号状态异常，无法显示");
                // 已经是好友了，该用户不存在，也会导致无法找到关键字  添加到通讯录。
                //那么,就将这一列，先放到临时的集合里。在任务结束时，更新数据。就更新此好友的状态为3(无法查找)
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 3, tastBatch);

                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                backInsert1();
                return;
            }

            //执行添加好友流程
            List<AccessibilityNodeInfo> list = nodeBase.findAccessibilityNodeInfosByText("添加到通讯录");
            if (list.size() == 0) {
                Log.d(TAG, "search2: 未找到  添加到通讯录");
            } else {
                AccessibilityNodeInfo nodeInfo = list.get(0);
                if(myDispatchGesture(nodeInfo))
                {
                    Log.d(TAG, "search2: 点击 添加到通讯录 成功！");
                    //这里会有2中情况，一种是直接就通过了好友请求。
                    //第二种是：申请添加朋友 页面  发起好友验证请求
                    //如果，你被添加成了黑名单，点击 添加到通讯录后，将无法跳转。
                    sendNew();
                } else {
                    Log.d(TAG, "search2: 点击 添加到通讯录 失败！");
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        //结束任务
                        this.disableSelf();
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "search2: 错误", e);
        }
    }

    /**
     * 模拟用户点击
     * @param node
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    private boolean myDispatchGesture(AccessibilityNodeInfo node) {
        Rect rect = new Rect();
        node.getBoundsInScreen(rect);
        Point position = new Point(rect.left + 10, rect.top + 10);
        GestureDescription.Builder builder = new GestureDescription.Builder();
        Path p = new Path();
        p.moveTo(position.x, position.y);
        builder.addStroke(new GestureDescription.StrokeDescription(p, 0L, 100L));
        GestureDescription gesture = builder.build();
        boolean isDispatched = dispatchGesture(gesture, new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                super.onCompleted(gestureDescription);
                Log.d(TAG, "onCompleted: 完成..........");
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                super.onCancelled(gestureDescription);
                Log.d(TAG, "onCompleted: 取消..........");
            }
        }, null);
        return isDispatched;
    }

    /**
     * 发送好友请求  申请添加朋友  com.tencent.mm:id/d6
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    private void sendNew() {
        try {
            Thread.sleep(800);
            //获取根节点
            List<AccessibilityNodeInfo> list = new ArrayList<>();
            Integer number = 0;
            while (number < 10) {
                Thread.sleep(1000);
                AccessibilityNodeInfo nodeBase = getRootInActiveWindow();
                if (nodeBase != null) {
                    list = nodeBase.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/d4y");
                    if (list.size() > 0) {
                        break;
                    }
                }
                number++;
                Thread.sleep(800);
            }

            //如果，没有找到标签。重新开始的流程。
            if (list.size() == 0) {
                //保存数据
                ContactsEntity cn = new ContactsEntity(contactsEntity.getId(), contactsEntity.getName(), contactsEntity.getCellPhone(), 3, tastBatch);
                //加入集合用于在任务结束时，更新数据。
                cnUpdateList.add(cn);
                backInsert2();
                return;
            }
            AccessibilityNodeInfo nodeInfo = list.get(0);
            boolean isClick=  myDispatchGesture(nodeInfo);
            if (isClick) {
                Thread.sleep(2000);
                //有时候，点击了发送按钮后，会没有反应
                Log.d(TAG, "send: 点击 发送 成功！");
                backInsert2();
            } else {
                Log.d(TAG, "send: 点击 发送 失败！");
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    //结束任务
                    this.disableSelf();
                }
            }
        } catch (Exception e) {
            Log.d(TAG, "send: " + e);
        }
    }

    /**
     * 返回到输入界面
     */
    private void backInsert1() {
        //发送成功后，点击返回按钮， 回到上一级页面，继续输入新的用户
        try {
            Thread.sleep(delay);
            performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
            Thread.sleep(delay);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                clickFirst();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回到输入界面
     */
    private void backInsert2() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                Thread.sleep(delay);
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                Thread.sleep(delay);
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                clickFirst();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 返回到输入界面
     */
    private void backInsert3() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                Thread.sleep(delay);
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                Thread.sleep(delay);
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                Thread.sleep(delay);
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                clickFirst();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
